/**
 * 
 */
package com.faxsun.core.service.impl;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import mblog.core.lang.Consts;
import mblog.core.persist.dao.TagDao;
import mblog.core.pojos.Post;
import mblog.core.pojos.Tag;
import mblog.core.utils.BeanMapUtils;
import mtons.modules.pojos.Page;
import mtons.modules.pojos.UserContextHolder;
import mtons.modules.pojos.UserProfile;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import com.faxsun.core.persist.entity.FollowListPO;
import com.faxsun.core.persist.entity.TagPO;
import com.faxsun.core.pojos.enums.TagType;
import com.faxsun.core.service.FollowListService;
import com.faxsun.core.service.PostService;
import com.faxsun.core.service.TagService;

/**
 * @author langhsu
 * @author songdragon
 *
 */
public class TagServiceImpl implements TagService {

	private static final Logger LOG = LoggerFactory.getLogger(TagServiceImpl.class);

	@Autowired
	private TagDao tagDao;
	@Autowired
	private PostService postService;
	@Autowired
	private FollowListService flService;

	@SuppressWarnings("unused")
	private final static String CACHE = "tagsCaches";

	@Override
	@Transactional(readOnly = true)
	public List<Tag> topTags(int maxResutls, boolean loadPost) {
		List<TagPO> list = tagDao.tops(maxResutls);

		List<Tag> rets = new ArrayList<Tag>();

		Set<Long> postIds = new HashSet<Long>();
		for (TagPO po : list) {
			rets.add(BeanMapUtils.copy(po));
			postIds.add(po.getLastPostId());
		}

		if (loadPost && postIds.size() > 0) {
			Map<Long, Post> posts = postService.findByIds(postIds);

			for (Tag t : rets) {
				Post p = posts.get(t.getLastPostId());
				t.setPost(p);
			}
		}
		return rets;
	}

	@Override
	@Transactional
	public void batchPost(List<Tag> tags) {
		if (tags == null || tags.size() == 0) {
			return;
		}

		for (Tag t : tags) {
			if (StringUtils.isBlank(t.getName())) {
				continue;
			}
			TagPO po = tagDao.getByName(t.getName());
			if (po != null) {
				po.setLastPostId(t.getLastPostId());
				po.setPosts(po.getPosts() + 1);
			} else {
				po = new TagPO();
				BeanUtils.copyProperties(t, po);
				tagDao.save(po);
			}
		}
	}

	@Override
	@Transactional
	public void identityHots(String name) {
		TagPO po = tagDao.getByName(name);
		if (po != null) {
			po.setHots(po.getHots() + Consts.IDENTITY_STEP);
		}
	}

	@Override
	@Transactional
	public void identityHots(long id) {
		TagPO po = tagDao.get(id);
		if (po != null) {
			po.setHots(po.getHots() + Consts.IDENTITY_STEP);
		}
	}

	@Override
	@Transactional(readOnly = true)
	// @Cacheable(value = CACHE, key =
	// "'listTags?pageNo'+#page.pageNo+'&maxResults='+#page.maxResults+'&tagType='+#tagType.value")
	public List<Tag> listTags(TagType tagType, Page page) {
		List<TagPO> tagPOs = tagDao.list(page, tagType);
		List<Tag> ret = new ArrayList<Tag>();
		for (TagPO tagPO : tagPOs) {
			Tag tag = new Tag();
			tag = BeanMapUtils.copy(tagPO);

			ret.add(tag);
		}
		page.setResults(ret);
		return ret;
	}

	@Override
	@Transactional
	public Tag saveTag(Tag tag) {
		long id = tag.getId();

		TagPO tagPO = null;
		if (id == 0) {
			if (tag.getName() == null) {
				LOG.error("Tag name is null, which is not expected");
				return null;
			}
			tagPO = tagDao.getByName(tag.getName());
		} else {
			tagPO = tagDao.get(id);
		}

		if (tagPO == null) {
			// 创建标签
			tagPO = new TagPO();
		}
		// 更新标签或设置标签内容
		tagPO.setEnumType(tag.getType());
		tagPO.setName(tag.getName());
		tagPO.setFeatured(tag.getFeatured());
		tagPO.setVideoUrl(tag.getVideoUrl());
		tagPO.setIsNav(tag.getIsNav());
		tagPO.setModule(tag.getModule());

		// 如果类型为商品（TagType.product）,且商品不是范客生活中商品，则设置商品信息
		if (tag.getType().equals(TagType.PRODUCT)) {
			// TODO:考虑商品不是范客生活的商品
		}

		tagDao.save(tagPO);
		tag = BeanMapUtils.copy(tagPO);
		return tag;
	}

	@Override
	@Transactional(readOnly = true)
	public Tag get(String name) {
		TagPO tagPO = tagDao.getByName(name);
		return BeanMapUtils.copy(tagPO);
	}

	@Override
	@Transactional(readOnly = true)
	public Tag getById(long id) {
		TagPO tagPO = tagDao.get(id);
		Tag tag = BeanMapUtils.copy(tagPO);
		if (tagPO.getEnumType() == TagType.PRODUCT) {
			long proTagId = tag.getId();
			int followed_count = flService.countAllMyFollowers(proTagId, 1);
			tag.setFollowsCounts(followed_count);

			int thumbsup_count = flService.countAllMyThumbsupers(proTagId, 1);
			tag.setThumbsupCounts(thumbsup_count);
			// FIXME:use profile instead of defualt user 1L
			UserProfile up = UserContextHolder.getUserProfile();
			// FollowListPO fl = flService.findFollow(proTagId, 1L, 1);
			FollowListPO fl = null;
			if (up != null) {
				fl = flService.findFollow(proTagId, up.getId(), 1);
				tag.setFollowerId(up.getId());
			} else {
				tag.setFollowerId(1);
			}
			String pro_followed = fl == null ? "false" : (fl.getStatus() == 0 ? "true" : "false");
			tag.setIsUserFollowd(pro_followed);
			String pro_thumbsup = fl == null ? "false" : (fl.getThumbsup() ? "true" : "false");
			tag.setIsUserThumbsup(pro_thumbsup);
		}
		return tag;
	}

	@Override
	@Transactional(readOnly = true)
	public List<Tag> queryTags(String tagName, Page page) {

		List<TagPO> tagPOs = tagDao.queryTag(tagName, page);
		List<Tag> ret = new ArrayList<Tag>();
		for (TagPO tagPO : tagPOs) {
			Tag tag = new Tag();
			tag = BeanMapUtils.copy(tagPO);

			ret.add(tag);
		}
		page.setResults(ret);
		return ret;
	}

	@Override
	@Transactional(readOnly = true)
	public boolean delete(Long id) {
		TagPO tag = tagDao.get(id);
		if (tag == null)
			return true;
		// FIXME: 使用枚举表示是否删除
		tag.setIsDeleted(1);

		// FIXME:清空相关关系数据
		tagDao.saveOrUpdate(tag);
		return true;
	}

	@Transactional
	@Override
	public void identityComments(Long id) {
		// FIXME: 直接在数据库中＋1，可能会由于并发事务，导致评论数不变，需要使用消息队列或者其他序列化操作
		TagPO product = tagDao.get(id);
		if (product != null && product.getEnumType() == TagType.PRODUCT) {
			product.setComments(product.getComments() + Consts.IDENTITY_STEP);
			tagDao.saveOrUpdate(product);
		}

	}

	@Transactional
	@Override
	public void identityComments(Long id, int step) {
		// FIXME: 直接在数据库中＋1，可能会由于并发事务，导致评论数不变，需要使用消息队列或者其他序列化操作
		TagPO product = tagDao.get(id);
		if (product != null && product.getEnumType() == TagType.PRODUCT) {
			product.setComments(product.getComments() + step);
			tagDao.saveOrUpdate(product);
		}

	}

	@Override
	@Transactional(readOnly = true)
	public List<Tag> listNavTags(int module) {
		List<TagPO> tagPOs = tagDao.listNavTags();
		Iterator<TagPO> it = tagPOs.iterator();
		while (it.hasNext()) {
			TagPO tag = it.next();
			// FIXME: use constant instead of magic number
			if (tag.getIsNav() && ((tag.getModule() & module) == module)) {
				continue;
			} else {
				it.remove();
			}
		}

		List<Tag> ret = new ArrayList<Tag>();
		for (TagPO tagPO : tagPOs) {
			ret.add(BeanMapUtils.copy(tagPO));
		}
		return ret;
	}

}
